package com.cyou.nad.utils;

import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.StringTokenizer;


public class StringUtils {

	/**
	 * StringUtils instances should NOT be constructed in standard programming.
	 * Instead, the class should be used as
	 * <code>StringUtils.trim(" foo ");</code>. This constructor is public to
	 * permit tools that require a JavaBean instance to operate.
	 */
	public StringUtils() {
	}

	// Empty
	// --------------------------------------------------------------------------

	/**
	 * Removes control characters, including whitespace, from both ends of this
	 * string, handling null by returning an empty string.
	 * 
	 * @see java.lang.String#trim()
	 * @param str
	 *            the string to check
	 * @return the trimmed text (never <code>null</code>)
	 */
	public static String clean(String str) {
		return (str == null ? "" : str.trim());
	}

	/**
	 * Removes control characters, including whitespace, from both ends of this
	 * string, handling null by returning null.
	 * 
	 * @see java.lang.String#trim()
	 * @param str
	 *            the string to check
	 * @return the trimmed text (or <code>null</code>)
	 */
	public static String trim(String str) {
		return (str == null ? null : str.trim());
	}

	/**
	 * Deletes all 'space' characters from a String. Spaces are defined as {' ',
	 * '\t', '\r', '\n', '\b'} in line with the deprecated Character.isSpace
	 * 
	 * @param str
	 *            String target to delete spaces from
	 * @return the text without spaces
	 * @throws NullPointerException
	 */
	// public static String deleteSpaces(String str) {
	// return CharSetUtils.delete(str, " \t\r\n\b");
	// }
	/**
	 * Deletes all whitespace from a String. Whitespace is defined by
	 * Character.isWhitespace
	 * 
	 * @param str
	 *            String target to delete whitespace from
	 * @return the text without whitespace
	 * @throws NullPointerException
	 */
	public static String deleteWhitespace(String str) {
		StringBuffer buffer = new StringBuffer();
		int sz = str.length();
		for (int i = 0; i < sz; i++) {
			if (!Character.isWhitespace(str.charAt(i))) {
				buffer.append(str.charAt(i));
			}
		}
		return buffer.toString();
	}

	/**
	 * Checks if a String is non null and is not empty (length > 0).
	 * 
	 * @param str
	 *            the string to check
	 * @return true if the String is non-null, and not length zero
	 */
	public static boolean isNotEmpty(String str) {
		return (str != null && str.length() > 0);
	}

	/**
	 * Checks if a (trimmed) String is null or empty.
	 * 
	 * @param str
	 *            the string to check
	 * @return true if the String is null, or length zero once trimmed
	 */
	public static boolean isEmpty(String str) {
		return (str == null || str.trim().length() == 0);
	}

	// Equals and IndexOf
	// --------------------------------------------------------------------------

	/**
	 * Compares two Strings, returning true if they are equal. Nulls are handled
	 * without exceptions. Two <code>null</code> references are considered
	 * equal. Comparison is case sensitive.
	 * 
	 * @see java.lang.String#equals(Object)
	 * @param str1
	 *            the first string
	 * @param str2
	 *            the second string
	 * @return true if the Strings are equal, case sensitive, or both null
	 */
	public static boolean equals(String str1, String str2) {
		return (str1 == null ? str2 == null : str1.equals(str2));
	}

	/**
	 * Compares two Strings, returning true if they are equal ignoring case.
	 * Nulls are handled without exceptions. Two <code>null</code> references
	 * are considered equal. Comparison is case insensitive.
	 * 
	 * @see java.lang.String#equalsIgnoreCase(String)
	 * @param str1
	 *            the first string
	 * @param str2
	 *            the second string
	 * @return true if the Strings are equal, case insensitive, or both null
	 */
	public static boolean equalsIgnoreCase(String str1, String str2) {
		return (str1 == null ? str2 == null : str1.equalsIgnoreCase(str2));
	}

	/**
	 * Find the earliest index of any of a set of potential substrings. Null
	 * string will return -1.
	 * 
	 * @param str
	 *            the string to check
	 * @param searchStrs
	 *            the strings to search for
	 * @return the earliest index of any of the strings
	 * @throws NullPointerException
	 *             if any of searchStrs[i] is null
	 */
	public static int indexOfAny(String str, String[] searchStrs) {
		if ((str == null) || (searchStrs == null)) {
			return -1;
		}
		int sz = searchStrs.length;

		// String's can't have a MAX_VALUEth index.
		int ret = Integer.MAX_VALUE;

		int tmp = 0;
		for (int i = 0; i < sz; i++) {
			tmp = str.indexOf(searchStrs[i]);
			if (tmp == -1) {
				continue;
			}

			if (tmp < ret) {
				ret = tmp;
			}
		}

		return (ret == Integer.MAX_VALUE) ? -1 : ret;
	}

	/**
	 * Find the latest index of any of a set of potential substrings. Null
	 * string will return -1.
	 * 
	 * @param str
	 *            the string to check
	 * @param searchStrs
	 *            the strings to search for
	 * @return the last index of any of the strings
	 * @throws NullPointerException
	 *             if any of searchStrs[i] is null
	 */
	public static int lastIndexOfAny(String str, String[] searchStrs) {
		if ((str == null) || (searchStrs == null)) {
			return -1;
		}
		int sz = searchStrs.length;
		int ret = -1;
		int tmp = 0;
		for (int i = 0; i < sz; i++) {
			tmp = str.lastIndexOf(searchStrs[i]);
			if (tmp > ret) {
				ret = tmp;
			}
		}
		return ret;
	}

	// Substring
	// --------------------------------------------------------------------------

	/**
	 * Gets a substring of the specified string avoiding exceptions. A negative
	 * start position can be used to start n characters from the end of the
	 * string.
	 * 
	 * @param str
	 *            the string to get the substring from
	 * @param start
	 *            the position to start from, negative means count back from the
	 *            end of the string by this many characters
	 * @return substring from start position
	 */
	public static String substring(String str, int start) {
		if (str == null) {
			return null;
		}

		// handle negatives, which means last n characters
		if (start < 0) {
			start = str.length() + start; // remember start is negative
		}

		if (start < 0) {
			start = 0;
		}
		if (start > str.length()) {
			return "";
		}

		return str.substring(start);
	}

	/**
	 * Gets a substring of the specified string avoiding exceptions. A negative
	 * start position can be used to start/end n characters from the end of the
	 * string.
	 * 
	 * @param str
	 *            the string to get the substring from
	 * @param start
	 *            the position to start from, negative means count back from the
	 *            end of the string by this many characters
	 * @param end
	 *            the position to end at (exclusive), negative means count back
	 *            from the end of the string by this many characters
	 * @return substring from start position to end positon
	 */
	public static String substring(String str, int start, int end) {
		if (str == null) {
			return null;
		}

		// handle negatives
		if (end < 0) {
			end = str.length() + end; // remember end is negative
		}
		if (start < 0) {
			start = str.length() + start; // remember start is negative
		}

		// check length next
		if (end > str.length()) {
			// check this works.
			end = str.length();
		}

		// if start is greater than end, return ""
		if (start > end) {
			return "";
		}

		if (start < 0) {
			start = 0;
		}
		if (end < 0) {
			end = 0;
		}

		return str.substring(start, end);
	}

	/**
	 * Gets the leftmost n characters of a string. If n characters are not
	 * available, or the string is null, the string will be returned without an
	 * exception.
	 * 
	 * @param str
	 *            the string to get the leftmost characters from
	 * @param len
	 *            the length of the required string
	 * @return the leftmost characters
	 * @throws IllegalArgumentException
	 *             if len is less than zero
	 */
	public static String left(String str, int len) {
		if (len < 0) {
			throw new IllegalArgumentException("Requested String length " + len + " is less than zero");
		}
		if ((str == null) || (str.length() <= len)) {
			return str;
		} else {
			return str.substring(0, len);
		}
	}

	/**
	 * Gets the rightmost n characters of a string. If n characters are not
	 * available, or the string is null, the string will be returned without an
	 * exception.
	 * 
	 * @param str
	 *            the string to get the rightmost characters from
	 * @param len
	 *            the length of the required string
	 * @return the leftmost characters
	 * @throws IllegalArgumentException
	 *             if len is less than zero
	 */
	public static String right(String str, int len) {
		if (len < 0) {
			throw new IllegalArgumentException("Requested String length " + len + " is less than zero");
		}
		if ((str == null) || (str.length() <= len)) {
			return str;
		} else {
			return str.substring(str.length() - len);
		}
	}

	/**
	 * Gets n characters from the middle of a string. If n characters are not
	 * available, the remainder of the string will be returned without an
	 * exception. If the string is null, null will be returned.
	 * 
	 * @param str
	 *            the string to get the characters from
	 * @param pos
	 *            the position to start from
	 * @param len
	 *            the length of the required string
	 * @return the leftmost characters
	 * @throws IndexOutOfBoundsException
	 *             if pos is out of bounds
	 * @throws IllegalArgumentException
	 *             if len is less than zero
	 */
	public static String mid(String str, int pos, int len) {
		if ((pos < 0) || (str != null && pos > str.length())) {
			throw new StringIndexOutOfBoundsException("String index " + pos + " is out of bounds");
		}
		if (len < 0) {
			throw new IllegalArgumentException("Requested String length " + len + " is less than zero");
		}
		if (str == null) {
			return null;
		}
		if (str.length() <= (pos + len)) {
			return str.substring(pos);
		} else {
			return str.substring(pos, pos + len);
		}
	}

	// Splitting
	// --------------------------------------------------------------------------

	/**
	 * Splits the provided text into a list, using whitespace as the separator.
	 * The separator is not included in the returned String array.
	 * 
	 * @param str
	 *            the string to parse
	 * @return an array of parsed Strings
	 */
	public static String[] split(String str) {
		return split(str, null, -1);
	}

	/**
	 * @see #split(String, String, int)
	 */
	public static String[] split(String text, String separator) {
		return split(text, separator, -1);
	}

	/**
	 * Splits the provided text into a list, based on a given separator. The
	 * separator is not included in the returned String array. The maximum
	 * number of splits to perfom can be controlled. A null separator will cause
	 * parsing to be on whitespace.
	 * 
	 * <p>
	 * This is useful for quickly splitting a string directly into an array of
	 * tokens, instead of an enumeration of tokens (as
	 * <code>StringTokenizer</code> does).
	 * 
	 * @param str
	 *            The string to parse.
	 * @param separator
	 *            Characters used as the delimiters. If <code>null</code>,
	 *            splits on whitespace.
	 * @param max
	 *            The maximum number of elements to include in the list. A zero
	 *            or negative value implies no limit.
	 * @return an array of parsed Strings
	 */
	public static String[] split(String str, String separator, int max) {
		StringTokenizer tok = null;
		if (separator == null) {
			// Null separator means we're using StringTokenizer's default
			// delimiter, which comprises all whitespace characters.
			tok = new StringTokenizer(str);
		} else {
			tok = new StringTokenizer(str, separator);
		}

		int listSize = tok.countTokens();
		if (max > 0 && listSize > max) {
			listSize = max;
		}

		String[] list = new String[listSize];
		int i = 0;
		int lastTokenBegin = 0;
		int lastTokenEnd = 0;
		while (tok.hasMoreTokens()) {
			if (max > 0 && i == listSize - 1) {
				// In the situation where we hit the max yet have
				// tokens left over in our input, the last list
				// element gets all remaining text.
				String endToken = tok.nextToken();
				lastTokenBegin = str.indexOf(endToken, lastTokenEnd);
				list[i] = str.substring(lastTokenBegin);
				break;
			} else {
				list[i] = tok.nextToken();
				lastTokenBegin = str.indexOf(list[i], lastTokenEnd);
				lastTokenEnd = lastTokenBegin + list[i].length();
			}
			i++;
		}
		return list;
	}

	// Joining
	// --------------------------------------------------------------------------
	/**
	 * Concatenates elements of an array into a single string. The difference
	 * from join is that concatenate has no delimiter.
	 * 
	 * @param array
	 *            the array of values to concatenate.
	 * @return the concatenated string.
	 */
	public static String concatenate(Object[] array) {
		return join(array, "");
	}

	/**
	 * Joins the elements of the provided array into a single string containing
	 * the provided list of elements. No delimiter is added before or after the
	 * list. A null separator is the same as a blank String.
	 * 
	 * @param array
	 *            the array of values to join together
	 * @param separator
	 *            the separator character to use
	 * @return the joined String
	 */
	public static String join(Object[] array, String separator) {
		if (separator == null) {
			separator = "";
		}
		int arraySize = array.length;
		int bufSize = (arraySize == 0 ? 0 : (array[0].toString().length() + separator.length()) * arraySize);
		StringBuffer buf = new StringBuffer(bufSize);

		for (int i = 0; i < arraySize; i++) {
			if (i > 0) {
				buf.append(separator);
			}
			buf.append(array[i]);
		}
		return buf.toString();
	}

	/**
	 * Joins the elements of the provided iterator into a single string
	 * containing the provided elements. No delimiter is added before or after
	 * the list. A null separator is the same as a blank String.
	 * 
	 * @param iterator
	 *            the iterator of values to join together
	 * @param separator
	 *            the separator character to use
	 * @return the joined String
	 */
	public static String join(Iterator iterator, String separator) {
		if (separator == null) {
			separator = "";
		}
		StringBuffer buf = new StringBuffer(256); // Java default is 16,
		// probably too small
		while (iterator.hasNext()) {
			buf.append(iterator.next());
			if (iterator.hasNext()) {
				buf.append(separator);
			}
		}
		return buf.toString();
	}

	// Replacing
	// --------------------------------------------------------------------------

	/**
	 * Replace a string with another string inside a larger string, once.
	 * 
	 * @see #replace(String text, String repl, String with, int max)
	 * @param text
	 *            text to search and replace in
	 * @param repl
	 *            String to search for
	 * @param with
	 *            String to replace with
	 * @return the text with any replacements processed
	 */
	public static String replaceOnce(String text, String repl, String with) {
		return replace(text, repl, with, 1);
	}

	/**
	 * Replace all occurances of a string within another string.
	 * 
	 * @see #replace(String text, String repl, String with, int max)
	 * @param text
	 *            text to search and replace in
	 * @param repl
	 *            String to search for
	 * @param with
	 *            String to replace with
	 * @return the text with any replacements processed
	 */
	public static String replace(String text, String repl, String with) {
		return replace(text, repl, with, -1);
	}

	/**
	 * Replace a string with another string inside a larger string, for the
	 * first <code>max</code> values of the search string. A <code>null</code>
	 * reference is passed to this method is a no-op.
	 * 
	 * @param text
	 *            text to search and replace in
	 * @param repl
	 *            String to search for
	 * @param with
	 *            String to replace with
	 * @param max
	 *            maximum number of values to replace, or <code>-1</code> if
	 *            no maximum
	 * @return the text with any replacements processed
	 * @throws NullPointerException
	 *             if repl is null
	 */
	public static String replace(String text, String repl, String with, int max) {
		if (text == null) {
			return null;
		}

		StringBuffer buf = new StringBuffer();
		int start = 0, end = 0;
		while ((end = text.indexOf(repl, start)) != -1) {
			buf.append(text.substring(start, end)).append(with);
			start = end + repl.length();

			if (--max == 0) {
				break;
			}
		}
		buf.append(text.substring(start));
		return buf.toString();
	}

	/**
	 * Overlay a part of a string with another string.
	 * 
	 * @param text
	 *            String to do overlaying in
	 * @param overlay
	 *            String to overlay
	 * @param start
	 *            int to start overlaying at
	 * @param end
	 *            int to stop overlaying before
	 * @return String with overlayed text
	 * @throws NullPointerException
	 *             if text or overlay is null
	 */
	public static String overlayString(String text, String overlay, int start, int end) {
		return new StringBuffer(start + overlay.length() + text.length() - end + 1).append(text.substring(0, start))
				.append(overlay).append(text.substring(end)).toString();
	}

	// Centering
	// --------------------------------------------------------------------------

	/**
	 * Center a string in a larger string of size n. Uses spaces as the value to
	 * buffer the string with. Equivalent to <code>center(str, size, "")</code>
	 * 
	 * @param str
	 *            String to center
	 * @param size
	 *            int size of new String
	 * @return String containing centered String
	 * @throws NullPointerException
	 *             if str is null
	 */
	public static String center(String str, int size) {
		return center(str, size, " ");
	}

	/**
	 * Center a string in a larger string of size n. Uses a supplied String as
	 * the value to buffer the string with..
	 * 
	 * @param str
	 *            String to center
	 * @param size
	 *            int size of new String
	 * @param delim
	 *            String to buffer the new String with
	 * @return String containing centered String
	 * @throws NullPointerException
	 *             if str or delim is null
	 * @throws ArithmeticException
	 *             if delim is the empty string
	 */
	public static String center(String str, int size, String delim) {
		int sz = str.length();
		int p = size - sz;
		if (p < 1) {
			return str;
		}
		str = leftPad(str, sz + p / 2, delim);
		str = rightPad(str, size, delim);
		return str;
	}

	// Chomping
	// --------------------------------------------------------------------------

	/**
	 * Remove the last newline, and everything after it from a String.
	 * 
	 * @param str
	 *            String to chomp the newline from
	 * @return String without chomped newline
	 * @throws NullPointerException
	 *             if str is null
	 */
	public static String chomp(String str) {
		return chomp(str, "\n");
	}

	/**
	 * Remove the last value of a supplied String, and everything after it from
	 * a String.
	 * 
	 * @param str
	 *            String to chomp from
	 * @param sep
	 *            String to chomp
	 * @return String without chomped ending
	 * @throws NullPointerException
	 *             if str or sep is null
	 */
	public static String chomp(String str, String sep) {
		int idx = str.lastIndexOf(sep);
		if (idx != -1) {
			return str.substring(0, idx);
		} else {
			return str;
		}
	}

	/**
	 * Remove a newline if and only if it is at the end of the supplied string.
	 * 
	 * @param str
	 *            String to chomp from
	 * @return String without chomped ending
	 * @throws NullPointerException
	 *             if str is null
	 */
	public static String chompLast(String str) {
		return chompLast(str, "\n");
	}

	/**
	 * Remove a value if and only if the string ends with that value.
	 * 
	 * @param str
	 *            String to chomp from
	 * @param sep
	 *            String to chomp
	 * @return String without chomped ending
	 * @throws NullPointerException
	 *             if str or sep is null
	 */
	public static String chompLast(String str, String sep) {
		if (str.length() == 0) {
			return str;
		}
		String sub = str.substring(str.length() - sep.length());
		if (sep.equals(sub)) {
			return str.substring(0, str.length() - sep.length());
		} else {
			return str;
		}
	}

	/**
	 * Remove everything and return the last value of a supplied String, and
	 * everything after it from a String.
	 * 
	 * @param str
	 *            String to chomp from
	 * @param sep
	 *            String to chomp
	 * @return String chomped
	 * @throws NullPointerException
	 *             if str or sep is null
	 */
	public static String getChomp(String str, String sep) {
		int idx = str.lastIndexOf(sep);
		if (idx == str.length() - sep.length()) {
			return sep;
		} else if (idx != -1) {
			return str.substring(idx);
		} else {
			return "";
		}
	}

	/**
	 * Remove the first value of a supplied String, and everything before it
	 * from a String.
	 * 
	 * @param str
	 *            String to chomp from
	 * @param sep
	 *            String to chomp
	 * @return String without chomped beginning
	 * @throws NullPointerException
	 *             if str or sep is null
	 */
	public static String prechomp(String str, String sep) {
		int idx = str.indexOf(sep);
		if (idx != -1) {
			return str.substring(idx + sep.length());
		} else {
			return str;
		}
	}

	/**
	 * Remove and return everything before the first value of a supplied String
	 * from another String.
	 * 
	 * @param str
	 *            String to chomp from
	 * @param sep
	 *            String to chomp
	 * @return String prechomped
	 * @throws NullPointerException
	 *             if str or sep is null
	 */
	public static String getPrechomp(String str, String sep) {
		int idx = str.indexOf(sep);
		if (idx != -1) {
			return str.substring(0, idx + sep.length());
		} else {
			return "";
		}
	}

	// Chopping
	// --------------------------------------------------------------------------

	/**
	 * Remove the last character from a String. If the String ends in \r\n, then
	 * remove both of them.
	 * 
	 * @param str
	 *            String to chop last character from
	 * @return String without last character
	 * @throws NullPointerException
	 *             if str is null
	 */
	public static String chop(String str) {
		if ("".equals(str)) {
			return "";
		}
		if (str.length() == 1) {
			return "";
		}
		int lastIdx = str.length() - 1;
		String ret = str.substring(0, lastIdx);
		char last = str.charAt(lastIdx);
		if (last == '\n') {
			if (ret.charAt(lastIdx - 1) == '\r') {
				return ret.substring(0, lastIdx - 1);
			}
		}
		return ret;
	}

	/**
	 * Remove \n from end of a String if it's there. If a \r precedes it, then
	 * remove that too.
	 * 
	 * @param str
	 *            String to chop a newline from
	 * @return String without newline
	 * @throws NullPointerException
	 *             if str is null
	 */
	public static String chopNewline(String str) {
		int lastIdx = str.length() - 1;
		char last = str.charAt(lastIdx);
		if (last == '\n') {
			if (str.charAt(lastIdx - 1) == '\r') {
				lastIdx--;
			}
		} else {
			lastIdx++;
		}
		return str.substring(0, lastIdx);
	}

	// Conversion
	// --------------------------------------------------------------------------

	// spec 3.10.6
	/**
	 * Escapes any values it finds into their String form. So a tab becomes the
	 * characters '\\' and 't'.
	 * 
	 * @param str
	 *            String to escape values in
	 * 
	 * @return String with escaped values
	 * @throws NullPointerException
	 *             if str is null
	 */
	public static String escape(String str) {
		// improved with code from cybertiger@cyberiantiger.org
		// unicode from him, and defaul for < 32's.
		int sz = str.length();
		StringBuffer buffer = new StringBuffer(2 * sz);
		for (int i = 0; i < sz; i++) {
			char ch = str.charAt(i);

			// handle unicode
			if (ch > 0xfff) {
				buffer.append("\\u" + Integer.toHexString(ch));
			} else if (ch > 0xff) {
				buffer.append("\\u0" + Integer.toHexString(ch));
			} else if (ch > 0x7f) {
				buffer.append("\\u00" + Integer.toHexString(ch));
			} else if (ch < 32) {
				switch (ch) {
				case '\b':
					buffer.append('\\');
					buffer.append('b');
					break;
				case '\n':
					buffer.append('\\');
					buffer.append('n');
					break;
				case '\t':
					buffer.append('\\');
					buffer.append('t');
					break;
				case '\f':
					buffer.append('\\');
					buffer.append('f');
					break;
				case '\r':
					buffer.append('\\');
					buffer.append('r');
					break;
				default:
					if (ch > 0xf) {
						buffer.append("\\u00" + Integer.toHexString(ch));
					} else {
						buffer.append("\\u000" + Integer.toHexString(ch));
					}
					break;
				}
			} else {
				switch (ch) {
				case '\'':
					buffer.append('\\');
					buffer.append('\'');
					break;
				case '"':
					buffer.append('\\');
					buffer.append('"');
					break;
				case '\\':
					buffer.append('\\');
					buffer.append('\\');
					break;
				default:
					buffer.append(ch);
					break;
				}
			}
		}
		return buffer.toString();
	}

	// Padding
	// --------------------------------------------------------------------------

	/**
	 * Repeat a string n times to form a new string.
	 * 
	 * @param str
	 *            String to repeat
	 * @param repeat
	 *            int number of times to repeat
	 * @return String with repeated string
	 * @throws NegativeArraySizeException
	 *             if repeat < 0
	 * @throws NullPointerException
	 *             if str is null
	 */
	public static String repeat(String str, int repeat) {
		StringBuffer buffer = new StringBuffer(repeat * str.length());
		for (int i = 0; i < repeat; i++) {
			buffer.append(str);
		}
		return buffer.toString();
	}

	/**
	 * Right pad a String with spaces. Pad to a size of n.
	 * 
	 * @param str
	 *            String to repeat
	 * @param size
	 *            int number of times to repeat
	 * @return right padded String
	 * @throws NullPointerException
	 *             if str is null
	 */
	public static String rightPad(String str, int size) {
		return rightPad(str, size, " ");
	}

	/**
	 * Right pad a String with a specified string. Pad to a size of n.
	 * 
	 * @param str
	 *            String to pad out
	 * @param size
	 *            int size to pad to
	 * @param delim
	 *            String to pad with
	 * @return right padded String
	 * @throws NullPointerException
	 *             if str or delim is null
	 * @throws ArithmeticException
	 *             if delim is the empty string
	 */
	public static String rightPad(String str, int size, String delim) {
		size = (size - str.length()) / delim.length();
		if (size > 0) {
			str += repeat(delim, size);
		}
		return str;
	}

	/**
	 * Left pad a String with spaces. Pad to a size of n.
	 * 
	 * @param str
	 *            String to pad out
	 * @param size
	 *            int size to pad to
	 * @return left padded String
	 * @throws NullPointerException
	 *             if str or delim is null
	 */
	public static String leftPad(String str, int size) {
		return leftPad(str, size, " ");
	}

	/**
	 * Left pad a String with a specified string. Pad to a size of n.
	 * 
	 * @param str
	 *            String to pad out
	 * @param size
	 *            int size to pad to
	 * @param delim
	 *            String to pad with
	 * @return left padded String
	 * @throws NullPointerException
	 *             if str or delim is null
	 * @throws ArithmeticException
	 *             if delim is the empty string
	 */
	public static String leftPad(String str, int size, String delim) {
		size = (size - str.length()) / delim.length();
		if (size > 0) {
			str = repeat(delim, size) + str;
		}
		return str;
	}

	// Stripping
	// --------------------------------------------------------------------------

	/**
	 * Remove whitespace from the front and back of a String.
	 * 
	 * @param str
	 *            the string to remove whitespace from
	 * @return the stripped string
	 */
	public static String strip(String str) {
		return strip(str, null);
	}

	/**
	 * Remove a specified String from the front and back of a String. If
	 * Whitespace is wanted to be removed, used the strip(String) method.
	 * 
	 * @param str
	 *            the string to remove a string from
	 * @param delim
	 *            the string to remove at start and end
	 * @return the stripped string
	 */
	public static String strip(String str, String delim) {
		str = stripStart(str, delim);
		return stripEnd(str, delim);
	}

	/**
	 * Strip whitespace from the front and back of every string in the array.
	 * 
	 * @param strs
	 *            the strings to remove whitespace from
	 * @return the stripped strings
	 */
	public static String[] stripAll(String[] strs) {
		return stripAll(strs, null);
	}

	/**
	 * Strip the specified delimiter from the front and back of every String in
	 * the array.
	 * 
	 * @param strs
	 *            the strings to remove a string from
	 * @param delimiter
	 *            the string to remove at start and end
	 * @return the stripped strings
	 */
	public static String[] stripAll(String[] strs, String delimiter) {
		if ((strs == null) || (strs.length == 0)) {
			return strs;
		}
		int sz = strs.length;
		String[] newArr = new String[sz];
		for (int i = 0; i < sz; i++) {
			newArr[i] = strip(strs[i], delimiter);
		}
		return newArr;
	}

	/**
	 * Strip any of a supplied string from the end of a String.. If the strip
	 * string is null, whitespace is stripped.
	 * 
	 * @param str
	 *            the string to remove characters from
	 * @param strip
	 *            the string to remove
	 * @return the stripped string
	 */
	public static String stripEnd(String str, String strip) {
		if (str == null) {
			return null;
		}
		int end = str.length();

		if (strip == null) {
			while ((end != 0) && Character.isWhitespace(str.charAt(end - 1))) {
				end--;
			}
		} else {
			while ((end != 0) && (strip.indexOf(str.charAt(end - 1)) != -1)) {
				end--;
			}
		}
		return str.substring(0, end);
	}

	/**
	 * Strip any of a supplied string from the start of a String. If the strip
	 * string is null, whitespace is stripped.
	 * 
	 * @param str
	 *            the string to remove characters from
	 * @param strip
	 *            the string to remove
	 * @return the stripped string
	 */
	public static String stripStart(String str, String strip) {
		if (str == null) {
			return null;
		}

		int start = 0;

		int sz = str.length();

		if (strip == null) {
			while ((start != sz) && Character.isWhitespace(str.charAt(start))) {
				start++;
			}
		} else {
			while ((start != sz) && (strip.indexOf(str.charAt(start)) != -1)) {
				start++;
			}
		}
		return str.substring(start);
	}

	// Case conversion
	// --------------------------------------------------------------------------

	/**
	 * Convert a String to upper case, null string returns null.
	 * 
	 * @param str
	 *            the string to uppercase
	 * @return the upper cased string
	 */
	public static String upperCase(String str) {
		if (str == null) {
			return null;
		}
		return str.toUpperCase();
	}

	/**
	 * Convert a String to lower case, null string returns null.
	 * 
	 * @param str
	 *            the string to lowercase
	 * @return the lower cased string
	 */
	public static String lowerCase(String str) {
		if (str == null) {
			return null;
		}
		return str.toLowerCase();
	}

	/**
	 * Uncapitalise a string. That is, convert the first character into
	 * lower-case. Null is returned as null.
	 * 
	 * @param str
	 *            the string to uncapitalise
	 * @return uncapitalised string
	 */
	public static String uncapitalise(String str) {
		if (str == null) {
			return null;
		}
		if (str.length() == 0) {
			return "";
		}
		return new StringBuffer(str.length()).append(Character.toLowerCase(str.charAt(0))).append(str.substring(1))
				.toString();
	}

	/**
	 * Capitalise a string. That is, convert the first character into
	 * title-case. Null is returned as null.
	 * 
	 * @param str
	 *            the string to capitalise
	 * @return capitalised string
	 */
	public static String capitalise(String str) {
		if (str == null) {
			return null;
		}
		if (str.length() == 0) {
			return "";
		}
		return new StringBuffer(str.length()).append(Character.toTitleCase(str.charAt(0))).append(str.substring(1))
				.toString();
	}

	/**
	 * Swaps the case of String. Properly looks after making sure the start of
	 * words are Titlecase and not Uppercase. Null is returned as null.
	 * 
	 * @param str
	 *            the string to swap the case of
	 * @return the modified string
	 */
	public static String swapCase(String str) {
		if (str == null) {
			return null;
		}
		int sz = str.length();
		StringBuffer buffer = new StringBuffer(sz);

		boolean whitespace = false;
		char ch = 0;
		char tmp = 0;

		for (int i = 0; i < sz; i++) {
			ch = str.charAt(i);
			if (Character.isUpperCase(ch)) {
				tmp = Character.toLowerCase(ch);
			} else if (Character.isTitleCase(ch)) {
				tmp = Character.toLowerCase(ch);
			} else if (Character.isLowerCase(ch)) {
				if (whitespace) {
					tmp = Character.toTitleCase(ch);
				} else {
					tmp = Character.toUpperCase(ch);
				}
			} else {
				tmp = ch;
			}
			buffer.append(tmp);
			whitespace = Character.isWhitespace(ch);
		}
		return buffer.toString();
	}

	/**
	 * Capitalise all the words in a string. Uses Character.isWhitespace as a
	 * separator between words. Null will return null.
	 * 
	 * @param str
	 *            the string to capitalise
	 * @return capitalised string
	 */
	public static String capitaliseAllWords(String str) {
		if (str == null) {
			return null;
		}
		int sz = str.length();
		StringBuffer buffer = new StringBuffer(sz);
		boolean space = true;
		for (int i = 0; i < sz; i++) {
			char ch = str.charAt(i);
			if (Character.isWhitespace(ch)) {
				buffer.append(ch);
				space = true;
			} else if (space) {
				buffer.append(Character.toTitleCase(ch));
				space = false;
			} else {
				buffer.append(ch);
			}
		}
		return buffer.toString();
	}

	// Nested extraction
	// --------------------------------------------------------------------------

	/**
	 * Get the String that is nested in between two instances of the same
	 * String. If str is null, will return null
	 * 
	 * @param str
	 *            the string containing nested-string
	 * @param tag
	 *            the string before and after nested-string
	 * @return the string that was nested, or null
	 * @throws NullPointerException
	 *             if tag is null
	 */
	public static String getNestedString(String str, String tag) {
		return getNestedString(str, tag, tag);
	}

	/**
	 * Get the string that is nested in between two strings.
	 * 
	 * @param str
	 *            the string containing nested-string
	 * @param open
	 *            the string before nested-string
	 * @param close
	 *            the string after nested-string
	 * @return the string that was nested, or null
	 * @throws NullPointerException
	 *             if open or close is null
	 */
	public static String getNestedString(String str, String open, String close) {
		if (str == null) {
			return null;
		}
		int start = str.indexOf(open);
		if (start != -1) {
			int end = str.indexOf(close, start + open.length());
			if (end != -1) {
				return str.substring(start + open.length(), end);
			}
		}
		return null;
	}

	/**
	 * How many times is the substring in the larger string. Null returns 0.
	 * 
	 * @param str
	 *            the string to check
	 * @param sub
	 *            the substring to count
	 * @return the number of occurances, 0 if the string is null
	 * @throws NullPointerException
	 *             if sub is null
	 */
	public static int countMatches(String str, String sub) {
		if (str == null) {
			return 0;
		}
		int count = 0;
		int idx = 0;
		while ((idx = str.indexOf(sub, idx)) != -1) {
			count++;
			idx += sub.length();
		}
		return count;
	}

	// Character Tests
	// --------------------------------------------------------------------------

	/**
	 * Checks if the string contains only unicode letters. Null will return
	 * false. The empty string will return true.
	 * 
	 * @param str
	 *            the string to check
	 * @return true if only contains letters, and is non-null
	 */
	public static boolean isAlpha(String str) {
		if (str == null) {
			return false;
		}
		int sz = str.length();
		for (int i = 0; i < sz; i++) {
			if (Character.isLetter(str.charAt(i)) == false) {
				return false;
			}
		}
		return true;
	}

	/**
	 * Checks if the string contains only unicode letters and space (' '). Null
	 * will return false. The empty string will return true.
	 * 
	 * @param str
	 *            the string to check
	 * @return true if only contains letters and space, and is non-null
	 */
	public static boolean isAlphaSpace(String str) {
		if (str == null) {
			return false;
		}
		int sz = str.length();
		for (int i = 0; i < sz; i++) {
			if ((Character.isLetter(str.charAt(i)) == false) && (str.charAt(i) != ' ')) {
				return false;
			}
		}
		return true;
	}

	/**
	 * Checks if the string contains only unicode letters or digits. Null will
	 * return false. The empty string will return true.
	 * 
	 * @param str
	 *            the string to check
	 * @return true if only contains letters or digits, and is non-null
	 */
	public static boolean isAlphanumeric(String str) {
		if (str == null) {
			return false;
		}
		int sz = str.length();
		for (int i = 0; i < sz; i++) {
			if (Character.isLetterOrDigit(str.charAt(i)) == false) {
				return false;
			}
		}
		return true;
	}

	/**
	 * Checks if the string contains only unicode letters, digits or space ('
	 * '). Null will return false. The empty string will return true.
	 * 
	 * @param str
	 *            the string to check
	 * @return true if only contains letters, digits or space, and is non-null
	 */
	public static boolean isAlphanumericSpace(String str) {
		if (str == null) {
			return false;
		}
		int sz = str.length();
		for (int i = 0; i < sz; i++) {
			if ((Character.isLetterOrDigit(str.charAt(i)) == false) && (str.charAt(i) != ' ')) {
				return false;
			}
		}
		return true;
	}

	/**
	 * Checks if the string contains only unicode digits. Null will return
	 * false. The empty string will return true.
	 * 
	 * @param str
	 *            the string to check
	 * @return true if only contains digits, and is non-null
	 */
	public static boolean isNumeric(String str) {
		if (str == null) {
			return false;
		}
		int sz = str.length();
		for (int i = 0; i < sz; i++) {
			if (Character.isDigit(str.charAt(i)) == false) {
				return false;
			}
		}
		return true;
	}

	/**
	 * Checks if the string contains only unicode digits or space (' '). Null
	 * will return false. The empty string will return true.
	 * 
	 * @param str
	 *            the string to check
	 * @return true if only contains digits or space, and is non-null
	 */
	public static boolean isNumericSpace(String str) {
		if (str == null) {
			return false;
		}
		int sz = str.length();
		for (int i = 0; i < sz; i++) {
			if ((Character.isDigit(str.charAt(i)) == false) && (str.charAt(i) != ' ')) {
				return false;
			}
		}
		return true;
	}

	// Defaults
	// --------------------------------------------------------------------------

	/**
	 * Return either the passed in String, or if it is null, then an empty
	 * String.
	 * 
	 * @param str
	 *            the string to check
	 * @return the passed in string, or blank if it was null
	 */
	public static String defaultString(String str) {
		return defaultString(str, "");
	}

	/**
	 * Return either the passed in String, or if it is null, then a passed in
	 * default String.
	 * 
	 * @param str
	 *            the string to check
	 * @param defaultString
	 *            the default string to return is str is null
	 * @return the passed in string, or the default if it was null
	 */
	public static String defaultString(String str, String defaultString) {
		return (str == null) ? defaultString : str;
	}

	// Reversing
	// --------------------------------------------------------------------------

	/**
	 * Reverse a String, null string returns null.
	 * 
	 * @param str
	 *            the string to reverse
	 * @return the reversed string
	 */
	public static String reverse(String str) {
		if (str == null) {
			return null;
		}
		return new StringBuffer(str).reverse().toString();
	}

	/**
	 * Reverses a string that is delimited by a specific character. The strings
	 * between the delimiters are not reversed. Thus java.lang.String becomes
	 * String.lang.java (if the delimiter is '.').
	 * 
	 * @param str
	 *            the string to reverse
	 * @param delimiter
	 *            the delimiter to use
	 * @return the reversed string
	 */
	public static String reverseDelimitedString(String str, String delimiter) {
		// could implement manually, but simple way is to reuse other,
		// probably slower, methods.
		String[] strs = split(str, delimiter);
		reverseArray(strs);
		return join(strs, delimiter);
	}

	/**
	 * Reverses an array. TAKEN FROM CollectionsUtils.
	 * 
	 * @param array
	 *            the array to reverse
	 */
	private static void reverseArray(Object[] array) {
		int i = 0;
		int j = array.length - 1;
		Object tmp;

		while (j > i) {
			tmp = array[j];
			array[j] = array[i];
			array[i] = tmp;
			j--;
			i++;
		}
	}

	// Misc
	// --------------------------------------------------------------------------

	/**
	 * Find the Levenshtein distance between two strings. This is the number of
	 * changes needed to change one string into another. Where each change is a
	 * single character modification.
	 * 
	 * This implemmentation of the levenshtein distance algorithm is from
	 * http://www.merriampark.com/ld.htm
	 * 
	 * @param s
	 *            the first String
	 * @param t
	 *            the second String
	 * @return int result distance
	 * @throws NullPointerException
	 *             if s or t is null
	 */
	/*
	 * public static int getLevenshteinDistance(String s, String t) { int d[][]; //
	 * matrix int n; // length of s int m; // length of t int i; // iterates
	 * through s int j; // iterates through t char s_i; // ith character of s
	 * char t_j; // jth character of t int cost; // cost // Step 1 n =
	 * s.length(); m = t.length(); if (n == 0) { return m; } if (m == 0) {
	 * return n; } d = new int[n + 1][m + 1]; // Step 2 for (i = 0; i <= n; i++) {
	 * d[i][0] = i; }
	 * 
	 * for (j = 0; j <= m; j++) { d[0][j] = j; } // Step 3 for (i = 1; i <= n;
	 * i++) { s_i = s.charAt(i - 1); // Step 4 for (j = 1; j <= m; j++) { t_j =
	 * t.charAt(j - 1); // Step 5 if (s_i == t_j) { cost = 0; } else { cost = 1; } //
	 * Step 6 d[i][j] = NumberUtils.minimum(d[i - 1][j] + 1, d[i][j - 1] + 1,
	 * d[i - 1][j - 1] + cost); } } // Step 7 return d[n][m]; }
	 */
	/**
	 * Checks if the String contains only certain chars.
	 * 
	 * @param str
	 *            the String to check
	 * @param valid
	 *            an array of valid chars
	 * @return true if it only contains valid chars and is non-null
	 */
	public static boolean containsOnly(String str, char[] valid) {
		if (str == null || valid == null) {
			return false;
		}

		int strSize = str.length();
		int validSize = valid.length;

		for (int i = 0; i < strSize; i++) {
			boolean contains = false;
			for (int j = 0; j < validSize; j++) {
				if (valid[j] == str.charAt(i)) {
					contains = true;
					break;
				}
			}
			if (!contains) {
				return false;
			}
		}

		return true;
	}

	public static String convertHTML(String str) {
		if (str == null)
			return "";
		str = str.replaceAll("&", "&amp;");
		str = str.replaceAll(">", "&gt;");
		str = str.replaceAll("<", "&lt;");
		return str;
	}

	public static String replaceParam(String source, String[] params) {
		for (int i = 0; i < params.length; i++) {
			String param = params[i];
			String find = "{" + i + "}";
			source = StringUtils.replace(source, find, param);
		}
		return source;
	}

	public static String parseString2Money(String moneyS) {
		int moneyI = Integer.parseInt(moneyS);
		StringBuffer sb = new StringBuffer();
		try {
			int yuan = moneyI / 100;
			int fen = moneyI % 100;
			sb.append(String.valueOf(yuan));
			sb.append(".");
			if (fen >= 10)
				sb.append(String.valueOf(fen));
			else
				sb.append("0").append(String.valueOf(fen));
		} catch (Exception e) {
		}
		return sb.toString();
	}

	public static String escapeSQLLike(String likeStr) {
		String str = StringUtils.replace(likeStr, "/", "//");
		str = StringUtils.replace(str, "_", "/_");
		str = StringUtils.replace(str, "%", "/%");
		str = StringUtils.replace(str, "?", "_");
		str = StringUtils.replace(str, "*", "%");

		return str;
	}

	/**
	 * 获取字符串长度，中文占两个字符
	 * @param string
	 * @return
	 */
	public static int getStrByteLen(String string) {
		if (null == string) {
			return 0;
		}
		char[] chars = string.toCharArray();
		int len = 0;
		for (char c : chars) {
			if (c < 256) {
				len++;
			} else {
				len += 2;
			}
		}
		return len;
	}


	public static String substringnew(String str, int size) {
		char[] chars = str.toCharArray();
		int len = 0;
		for (int i = 0; i < chars.length; i++) {
			if (chars[i] < 256) {
				len++;
			} else {
				len += 2;
			}
			if (len > size)
				return str.substring(0, i - 1);
			else if (len == size)
				return str.substring(0, i);
		}
		return str;
	}
	
	public static String formatExcelString(String value) {
		if (null == value) {
			return "";
		}

		char unhandleChar1 = (char) 160;

		value = value.replace(unhandleChar1, ' ');
		value = value.replace("\t", "");
		value = value.replace("\r", "");
		value = value.replace("\n", "");

		return value.trim();
	}
	
	public static void main(String[] args){
		//String s = StringUtils.QBchange("'!@#%");
		String s = "''��|'''";
		System.out.println(s.replaceAll("'", "''"));
	}

}
